package org.geosearch;

import static org.geoscrape.util.ParamParser.getParameter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.geoscrape.Cache;
import org.geoscrape.Location;
import org.geoscrape.Login;
import org.geoscrape.ListSearcher;

/**
 * Program that searches for new caches within a given range.
 *
 */
public class NewCacheSearcher
{

	/**
	 * @param args
	 * @throws IOException 
	 * @throws ParseException 
	 */
	public static void main(String[] args) throws IOException, ParseException
	{
		String name = getParameter("n", args);
		String password = getParameter("p", args);
		String outputFile = getParameter("o", args);
		String coordinates = getParameter("c",args);
		String distance = getParameter("d",args);
		if (verifyInputs(name, password, outputFile, coordinates, distance))
		{
			Login login = new Login(name, password);
			login.authenticate();
			int minSeconds = 0;
			int maxSeconds = 0;
			String delays = getParameter("r", args);
			if (delays != null)
			{
				String[] dparts = delays.split("-");
				if (dparts.length != 2)
				{
					System.out
							.println("Random delays must be given in the format <lowest>-<highest>");
					System.exit(1);
				}
				minSeconds = Integer.parseInt(dparts[0]);
				maxSeconds = Integer.parseInt(dparts[1]);
			}
			Location loc = new Location(coordinates);
			double dist = Double.parseDouble(distance);
			doSearch(login,outputFile,loc,dist,minSeconds,maxSeconds);
			System.exit(0);
		}
		else
		{
			System.exit(1);
		}

	} 
	
	public static void doSearch(Login login, String outputFile,
			Location loc, double dist, int minSeconds, int maxSeconds) throws IOException, ParseException
	{
		ListSearcher s = new ListSearcher(login);
		if (minSeconds <= maxSeconds && maxSeconds > 0)
		{
			s.setMinSeconds(minSeconds);
			s.setMaxSeconds(maxSeconds);
			s.setUseRandomDelay(true);
		}
		List<Cache> found = s.findCachesCloseTo(loc, dist,true);
		File dbFile = new File(outputFile);
		if(!dbFile.exists())
		{
			//create the db file
			FileWriter fw = new FileWriter(dbFile);
			for(Cache c:found)
			{
				fw.write(c.getCacheCode());
				fw.write("\n");
			}
			fw.close();
		}
		else
		{
			//compare the db file to the found caches.
			//first load the known caches
			List<String>knownCaches = new ArrayList<String>();
			BufferedReader br = new BufferedReader(new FileReader(dbFile));
			String line = br.readLine();
			while(line != null)
			{
				if(!knownCaches.contains(line))
				{
					knownCaches.add(line);
				}
				line = br.readLine();
			}
			br.close();
			//compare the known caches to the found ones
			for(Cache c:found)
			{
				if(!knownCaches.contains(c.getCacheCode()))
				{
					//output the new cache code
					System.out.println(c.getCacheCode());
					//add the new cache code to the known caches
					knownCaches.add(c.getCacheCode());
				}
			}
			//re-create the db file
			FileWriter fw = new FileWriter(dbFile,false);
			for(String c:knownCaches)
			{
				fw.write(c);
				fw.write("\n");
			}
			fw.close();
			
		}
		
	}
	/**
	 * Sanity checks on the required input values.
	 * 
	 * @param name
	 * @param password
	 * @param outputFile
	 */
	private static boolean verifyInputs(String name, String password, String outputFile,String location,String distance)
	{
		boolean allCorrect = true;
		if (name == null || name == "")
		{
			System.out.println("You must supply a user name.");
			allCorrect = false;
		}
		if (password == null)
		{
			System.out.println("You must supply a password.");
			allCorrect = false;
		}
		if (outputFile == null)
		{
			System.out.println("You must supply a database file name.");
			allCorrect = false;
		}
		if (location == null)
		{
			System.out.println("You must supply a search location.");
			allCorrect = false;
		}
		if (distance == null)
		{
			System.out.println("You must supply a search distance.");
			allCorrect = false;
		}
		if (!allCorrect)
		{
			System.out.println();
			System.out.println("Usage:");
			System.out
					.println("NewCacheSearcher -n <username> -p <password> -o <database filename> -c <coordinates> -d <search distance>  [-r <time range>]");
			System.out.println(" Parameters:");
			System.out.println(" -n The GC.com username to log in as.");
			System.out.println(" -p The password for the given username.");
			System.out
			.println(" -o The database file name. If the file does not exist it will be created.");
			System.out
			.println("    If the file does not exist (for example, if this is the first time you run the program),");

			System.out
			.println("    NewCacheSearcher will create a new file, fill in all caches, then exit, without printing output.");
			System.out
			.println("    If the file does exist NewCacheSearcher will output all caches that are not in the file. The file is then updated and the program exits.");
	System.out
			.println(" -c The location to search around, in DD MM.MMM format, for example \"N 34 55.573 W 080 58.358\" - note that degree symbols are optional.");
	System.out.println("    The coordinates MUST be enclosed in double quotes.");
			System.out
			.println(" -d The distance, in kilometres, from the location to search for caches.");
			System.out
					.println(" -r The time-delay range to use, on the format <lowest>-<highest>. Measured in seconds.");
			System.out.println("    Example: -r 4-28");
			System.out
					.println("    which gives random delays for each request between 4 and 28 seconds.");
			System.out
					.println("    If this parameter is not given, no delay will be used.");
		}
		return allCorrect;
	}
}
